We will explore patterns in collocated and temporally-similar (within 1 hour) night-time buoy MODIS AQUA and VIIRS retrievals and how those patterns change when only records where both AQUA and VIIRS SSTs have a quality level of 0.

Matchups were joined by buoy date and id. A set of filtering criterion were then imposed onto the joint matchups to ensure that the joint retrievals were actually measurements of the same SST under similar atmospheric conditions.

orig_solz_platform_time are the collocated, temporally-similar, night-time, buoy AQUA and VIIRS retrievals where the distance between the satellite and the buoy is not more than 1 km at the time of the retrieval (referred to as “standard filtering”).

orig_filtered is orig_solz_platform_time (standard filtering) where only retrievals where both AQUA and VIIRS quality levels are 0 are included.

Cross-Tabulation Tables

Cross-tabulation of VIIRS and AQUA matchups filtered by solz, platform, and time difference <= 1 hrs

This table shows the cross tabulation of quality levels in AQUA and VIIRS matchups from orig_solz_platform_time. Note the large quantity of AQUA retrievals that have a quality of 3 when their respective VIIRS counterparts have a quality level of 0.

xtabs(~ qsst.AQUA + qsst.VIIRS, data = orig_solz_platform_time)
##          qsst.VIIRS
## qsst.AQUA     0     1     2     3
##         0 19718  2749    13  1035
##         1  5002  1461    18   723
##         2  2563   981    40   645
##         3  2808   581   115 15500
##         4     8     2     0     6

Plots of features in AQUA and VIIRS matchups

Here we attempt plot features in the AQUA and VIIRS matchups to (a) check that the joining and filtering has been implemented correctly and (b) identify any other discrepancies that could help us understand the quality discrepancy. For every feature we explore, we will explore it both in orig_solz_platform_time and orig_filtered. ggplot2 will be used to do the plotting

Plots of SSTs in VIIRS and AQUA matchups filtered by solz, platform, and time difference <= 1 hrs

Central SST of VIIRS and AQUA matchups

ggplot2::ggplot(data = orig_solz_platform_time, mapping = aes(x = cen.sst.AQUA, y = cen.sst.VIIRS)) +
  stat_bin2d(bins = 100) +
  geom_abline(intercept = 0, slope = 1, color = "tomato") +
  ggtitle("VIIRS and AQUA SSTS") +
  labs(caption = "VIIRS SSTs against AQUA SSTs with standard filtering (night-time, temporally-similar, buoy retrievals with the distance between the satellite and buoy not more than 1 km). Note the deviation from the y = x line.")
## Warning: Removed 4 rows containing non-finite values (stat_bin2d).

Central SST of VIIRS and AQUA matchups with coloring by AQUA QSST

ggplot2::ggplot(data = orig_solz_platform_time, mapping = aes(x = cen.sst.AQUA, y = cen.sst.VIIRS,
  alpha = 0.2, color = as.factor(qsst.AQUA))) +
  geom_point() +
  geom_abline(intercept = 0, slope = 1, color = "tomato") +
  ggtitle(label = "VIIRS and AQUA SSTs colored by AQUA QSST") +
  labs(caption = "VIIRS SSTs against AQUA SSTs with standard filtering. Note the points that deviate from the y = x line have a quality not equal to 0.")
## Warning: Removed 4 rows containing missing values (geom_point).

Central SST of VIIRS and AQUA matchups with coloring by VIIRS QSST

ggplot2::ggplot(data = orig_solz_platform_time, mapping = aes(x = cen.sst.AQUA, y = cen.sst.VIIRS,
  alpha = 0.2, color = as.factor(qsst.VIIRS))) +
  geom_point() +
  geom_abline(intercept = 0, slope = 1, color = "tomato") +
  ggtitle(label = "VIIRS and AQUA SSTs colored by VIIRS QSST") +
  labs(caption = "VIIRS SSTs against AQUA SSTs with standard filtering. Note the points that deviate from the y = x line have a quality not equal to 0.")
## Warning: Removed 4 rows containing missing values (geom_point).

Faceted plot with QSSTs

ggplot2::ggplot(data = orig_solz_platform_time, mapping = aes(x = cen.sst.AQUA, y = cen.sst.VIIRS)) +
  stat_bin2d(bins = 100) +
  facet_grid(qsst.AQUA ~ qsst.VIIRS) +
  ggtitle(label = "VIIRS and AQUA SSTs faceted by both VIIRS and AQUA QSSTs") +
  labs(caption = "VIIRS SSTs against AQUA SSTs with standard filtering.")
## Warning: Removed 4 rows containing non-finite values (stat_bin2d).

Here we break down the above plots by both AQUA and VIIRS QSSTs, creating a visual form of the above Cross-Tabulation table. Here a possible explanation is provided for both the abnormally large amount of AQUA retrievals with a QSST of 3 where their VIIRS counterpart has a QSST of 0 and the above plot. Note that often points with an AQUA QSST of 3 are higher than the \(y = x\) line (Their VIIRS retrievals have higher SST values) and points with a VIIRS QSST of 3 are below the same line. These trends can be attributed to (a) the use of Alternating Decision Trees for cloud identification on VIIRS matchups which has shown that many matchups flagged with an AQUA QSST of 3 have been erroneosly labeled and (b) clouds. Because a maximum of 1 hour can elapse between VIIRS and AQUA passing over the same point (as per our filtering requirements), cloud distribution over that point can change. For example, when AQUA passes over a point, that point may be cloud contaminated but when VIIRS passes over, the clouds may have moved making that point free of clouds. Therefore, an AQUA retrieval can be flagged as QSST of 3 when the respective VIIRS QSST can be 0.

Central SST in AQUA and VIIRS matchups with quality filtering

ggplot2::ggplot(data = orig_filtered, mapping = aes(x = cen.sst.AQUA, y = cen.sst.VIIRS)) +
  stat_bin2d(bins = 100) +
  geom_abline(intercept = 0, slope = 1, color = "tomato") +
  ggtitle(label = "VIIRS and AQUA SSTs") +
  labs(caption = "VIIRS against AQUA SSTs with standard filtering and the addition of only points with a QSST of zero in both AQUA and VIIRS matchups are included.")

Notice that much of the deviation from the \(y = x\) line in the first plot is removed when we constrict the data to only matchups with both AQUA and VIIRS qualities equal to 0.

Plots of the BT in the 11 \(mu\)m channel over the central pixel

Because SST is a function of the Brightness Temperature in the 11 \(mu\)m, let us see if we find the same QSST and distribution patterns in plots of VIIRS cen.11000 against AQUA cen.11000 ###Cen.11000 in VIIRS and AQUA matchups filtered by solz, platform, and time difference <= 1 hrs

ggplot2::ggplot(data = orig_solz_platform_time, mapping = aes(x = cen.11000.AQUA, y = cen.11000.VIIRS)) +
  stat_bin2d(bins = 100) +
  geom_abline(intercept = 0, slope = 1, color = "tomato") +
  ggtitle(label = "VIIRS and AQUA 11 micrometer BTs") +
  labs(caption = "VIIRS 11 micrometer BT against AQUA 11 micrometer BT with the standard filtering.")

Cen.11000 in AQUA and VIIRS matchups with quality filtering

ggplot2::ggplot(data = orig_filtered, mapping = aes(x = cen.11000.AQUA, y = cen.11000.VIIRS)) +
  stat_bin2d(bins = 100) +
  geom_abline(intercept = 0, slope = 1, color = "tomato") +
  ggtitle("VIIRS 11 micrometer BTs against AQUA 11 micrometer BTs from collocated and temporally-similar matchups with VIIRS and AQUA quality levels of 0.") +
  labs(caption = "VIIRS 11 micrometer BT against AQUA 11 micrometer BT with standard and QSST filtering.")

Notice that much of the deviation from the \(y = x\) line in the first plots is again removed when we constrict the data to only matchups with both AQUA and VIIRS qualities equal to 0.

Histograms of time distributions between satellite times and satellite and buoy times

We will explore 3 separate histograms to try and get an idea of the distribution of the time difference between when the buoy takes an SST measurement and when AQUA and VIIRS retrieve an SST value that matches with the buoys measurement. We will also explore the time difference between AQUA and VIIRS passing over the same buoy, and therefore the same location.

Distribution of time differences between AQUA and respective AQUA buoy retrievals

ggplot2::ggplot(data = orig_filtered, mapping = aes(x = sat.pftime.AQUA - buoy.pftime.AQUA)) +
  geom_histogram(bins = 100) +
  ggtitle(label = "Time differences between AQUA and respective AQUA buoy retrievals") +
  xlim(-3600, 3600)

Distribution of time differences between VIIRS and respective VIIRS buoy retrievals

ggplot2::ggplot(data = orig_filtered, mapping = aes(x = sat.pftime.VIIRS - buoy.pftime.VIIRS)) +
  geom_histogram(bins = 100) +
  ggtitle(label = "Time differences between VIIRS and respective VIIRS buoy retrievals") +
  xlim(-3600, 3600)

Distribution of time differences between AQUA and respective VIIRS retrievals

ggplot2::ggplot(data = orig_filtered, mapping = aes(x = sat.pftime.AQUA - sat.pftime.VIIRS)) +
  geom_histogram(bins = 100) +
  ggtitle(label = "Time differences between AQUA retrievals and respective VIIRS retrievals") +
  xlim(-7200, 7200)

Interactive Maps of Retrieval Locations

matchup.coords <- as.matrix(cbind(lon = orig_filtered[, 'buoy.lon.AQUA'],
  lat = orig_filtered[, 'buoy.lat.AQUA']))

crs.string <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"

pts <- sp::SpatialPoints(coords = matchup.coords,
  proj4string = sp::CRS(crs.string))

pts <- as.data.frame(pts)
pts <- data.frame(pts, orig_filtered$insitu.platform.AQUA, orig_filtered$buoy.id)
sp::coordinates(pts) <- ~ buoy.lon.AQUA + buoy.lat.AQUA
sp::proj4string(pts) <- sp::CRS(crs.string)

mapview::mapview(pts, alpha = .2, cex = 1)